/*!
 * \file ExecutionPlan.h
 * \brief Defines an ExecutionPlan class as plan to execute after parsing the
 *        arguments
 *
 * This file contains the definition for the CLAP :: ExecutionPlan Class. This
 * is a class to generate an execution plan given inputs and a set of options
 * and subcommands available.
 */

#ifndef _CLAP_EXECUTIONPLAN_H_
#define _CLAP_EXECUTIONPLAN_H_

#include "Types.h"
#include "Stage.h"
#include "Exception.h"

using namespace libCLAP;

namespace libCLAP
{
   namespace CLAP
   {
      class Stage;
      /*!
       * \class ExecutionPlan
       * \brief A class to define an execution plan object for a given input.
       *
       * An ExecutionPlan is a sequence of Stages, that contain switches
       * and also arguments for each step of command execution. This class is
       * essentially a doubly linked list of Stages. A Stage can only have
       * one parent and one child. Also when adding stages they have to be
       * added sequentially.
       *
       * For example : NULL <- Stage1 <-> Stage2 <-> Stage3 -> NULL
       * That would be an example of what the execution plan structure would
       * look like.
       */
      class ExecutionPlan
      {
         public :

         typedef list < Stage > :: iterator Iterator;
         typedef list < Stage > :: const_iterator ConstIterator;
         typedef list < Stage > :: reverse_iterator ReverseIterator;
         typedef list < Stage > :: const_reverse_iterator ConstReverseIterator;

         /*!
          * \brief Constructor
          *
          * Constructor for the Development :: CLAP ::
          * ExecutionPlan
          *
          * \param name A String that holds the name of hte main stage.
          */
         ExecutionPlan ( const Common :: String & name );

         /*!
          * \brief Copy Constructor
          *
          * Constructor for the Development :: CLAP ::
          * ExecutionPlan that cnstructs the object as a copy of the parameter
          *
          * \param copy An ExecutionPlan that holds the ExecutionPlan to be
          *             copied.
          */
         ExecutionPlan ( const ExecutionPlan & copy );

         /*!
          * \brief Destructor
          */
         virtual ~ExecutionPlan ( void ) throw ();

         /*!
          * \brief An AddStage Function
          *
          * This function allows you to add a stage onto the ExecutionPlan.
          * The Stage is only added at the end of the ExecutionPlan. That is
          * there cannot be multiple stages associated with one stage and
          * stages cannot be added in the middle of the Plan, they must be
          * added in order.
          *
          * \param addition A Stage object to be added onto the queue. This
          *                 should be allocated on the heap since, we will
          *                 not copy the stage locally.
          */
         virtual void AddStage ( const Stage & addition );

         /*!
          * \brief Operator =
          *
          * This operator can be used to set another ExecutionPlan type to this.
          * parameter ExecutionPlan type.
          *
          * \param assign This is the ExecutionPlan to set equal to.
          *
          * \return This ExecutionPlan
          */
         virtual ExecutionPlan & operator = ( const ExecutionPlan & assign );

         /*!
          * \brief Operator ==
          *
          * This operator can be used to check if two ExecutionPlan objects are equal to
          * eachother.
          *
          * \param compare This is the ExecutionPlan to check for equality
          *
          * \return A bool that is true if the two ExecutionPlan objects are equal
          */
         virtual bool operator == ( const ExecutionPlan & compare ) const;

         /*!
          * \brief Operator !=
          *
          * This operator can be used to check if two ExecutionPlan objects are inequal to
          * eachother.
          *
          * \param compare This is the ExecutionPlan to check for inequality
          *
          * \return A bool that is true if the two ExecutionPlan objects aren't equal
          */
         virtual bool operator != ( const ExecutionPlan & compare ) const;

         /*!
          * \brief Operator <
          *
          * This operator is used to check if this ExecutionPlan object is less than the
          * parameter ExecutionPlan object.
          *
          * \param compare This is the ExecutionPlan to compare with.
          *
          * \return A bool that is true if this Stage opject is less than the
          *         parameter stage object.
          */
         virtual bool operator < ( const ExecutionPlan & compare ) const;

         /*!
          * \brief Operator >
          *
          * This operator is used to check if this ExecutionPlan object is greater than the
          * parameter ExecutionPlan object.
          *
          * \param compare This is the ExecutionPlan to compare with.
          *
          * \return A bool that is true if this Stage opject is greater than the
          *         parameter stage object.
          */
         virtual bool operator > ( const ExecutionPlan & compare ) const;

         /*!
          * \brief End function
          *
          * Function to return the End iterator
          *
          * \return An Iterator that is the End of the object
          */
         virtual Iterator End ( void );

         /*!
          * \brief Begin function
          *
          * Function to return the Beginning iterator
          *
          * \return An Iterator that is the Beginning of the ExecutionPlan object
          */
         virtual Iterator Begin ( void );

         /*!
          * \brief End function
          *
          * Function to return the End iterator
          *
          * \return An ConstIterator that is the End of the ExecutionPlan object
          */
         virtual ConstIterator End ( void ) const;

         /*!
          * \brief Begin function
          *
          * Function to return the Beginning iterator
          *
          * \return An ConstIterator that is the Beginning of the ExecutionPlan object
          */
         virtual ConstIterator Begin ( void ) const;

         /*!
          * \brief ReverseEnd function
          *
          * Function to return the End iterator
          *
          * \return An Iterator that is the End of the ExecutionPlan object
          */
         virtual ReverseIterator ReverseEnd ( void );

         /*!
          * \brief ReverseBegin function
          *
          * Function to return the Beginning iterator
          *
          * \return An Iterator that is the Beginning of the ExecutionPlan object
          */
         virtual ReverseIterator ReverseBegin ( void );

         /*!
          * \brief ReverseEnd function
          *
          * Function to return the End iterator
          *
          * \return An ConstIterator that is the End of the ExecutionPlan object
          */
         virtual ConstReverseIterator ReverseEnd ( void ) const;

         /*!
          * \brief ReverseBegin function
          *
          * Function to return the Beginning iterator
          *
          * \return An ConstIterator that is the Beginning of the ExecutionPlan object
          */
         virtual ConstReverseIterator ReverseBegin ( void ) const;

         private :

         list < Stage > _Stages;
      };
   }
}
#endif
